<?php

class Model {

    private $version = '';       //mysql版本
    private $config = array();   //数据库配置数组 
    private $class;	      //当前类名
    public $tablepre = '';      //表前缀
    public $db = '';	    //库名    
    public $table = '';	 //表名
    private static $link;	//数据库链接句柄
    private $data = array();     //中间数据容器
    private $condition = '';    //查询条件
    private $fields = array();   //字段信息
    private $sql = array();      //sql集合，调试用
    public $primaryKey = 'id';  //表主键

    //构造函数初始化

    public function __construct($options = array()) {
	//如果参数只是一个一般的字符串，则认为是实例化一个没有模型文件的Model
	if (is_string($options)) {
	    $this->table = $options;
	}
	//如果参数是数组，则认为是数据库配置文件，为空则使用默认配置文件  
	$this->config = (is_array($options) && !empty($options)) ? $options : AppConfig::$dbParam;
	$this->connect();
	$this->init();
    }

    //链接数据库
    private function connect() {
	if ($this->config['dbPconnect']) {
	    self::$link = @mysql_pconnect($this->config['dbHost'], $this->config['dbUser'], $this->config['dbPassword']);
	} else {
	    self::$link = @mysql_connect($this->config['dbHost'], $this->config['dbUser'], $this->config['dbPassword'], true);
	}
	!self::$link && $this->errdie('Could not connect Mysql: ');

	$this->db = !empty($this->db) ? $this->db : $this->config['dbName'];
	$serverinfo = $this->version();
	if ($serverinfo > '4.1' && $this->config['dbCharset']) {
	    mysql_query("SET character_set_connection=" . $this->config['dbCharset'] . ",character_set_results=" . $this->config['dbCharset'] . ",character_set_client=binary", self::$link);
	}
	if ($serverinfo > '5.0') {
	    mysql_query("SET sql_mode=''", self::$link);
	}
	@mysql_select_db($this->db, self::$link) or $this->errdie('Cannot use database');
	return self::$link;
    }

    //表基本信息初始化
    protected function init() {
	$this->class = get_class($this);
	$this->table = !empty($this->table) ? $this->table : strtolower($this->class);
	$this->table = $this->tablepre . $this->table;
	return $this;
    }

    //设置属性值
    public function __set($name, $value) {
	$this->data['fields'][$name] = $value;
    }

    //获取属性值
    public function __get($name) {
	if (isset($this->data['fields'][$name])) {
	    return($this->data['fields'][$name]);
	} else {
	    return NULL;
	}
    }

    //字段信息处理
    private function implodefields($data) {
	if (!is_array($data)) {
	    $data = array();
	}
	$this->fields = !empty($this->data['fields']) ? array_merge($this->data['fields'], $data) : $data;
	foreach ($this->fields as $key => $value) {
	    $fieldsNameValueStr[] = "`$key`='$value'";
	    $fieldsNameStr[] = "`$key`";
	    $fieldsValueStr[] = "'$value'";
	}
	return array($fieldsNameValueStr, $fieldsNameStr, $fieldsValueStr);
    }

    //条件判断组装
    private function condition($where = NULL) {
	if (is_numeric($where)) {
	    $where = "WHERE `{$this->primaryKey}`='{$where}' LIMIT 1";
	} elseif (is_array($where)) {
	    $where = "WHERE `{$this->primaryKey}` in (" . implode(',', $where) . ")";
	} elseif (!empty($this->data['condition'])) {
	    //'预留WHERE', 'order', 'group', 'limit' …………等条件关键词处理接口
	    $where = $where ? "WHERE {$where}" : "WHERE 1";
	    isset($this->data['condition']['where']) && $where .= ' AND ' . $this->data['condition']['where'];
	    isset($this->data['condition']['group']) && $where .= ' GROUP BY ' . $this->data['condition']['group'];
	    isset($this->data['condition']['order']) && $where .= ' ORDER BY ' . $this->data['condition']['order'];
	    isset($this->data['condition']['limit']) && $where .= ' LIMIT ' . $this->data['condition']['limit'];
	} else {
	    $where = "WHERE {$where}";
	}
	$this->condition = $where;
	return $this;
    }

    //插入数据
    public function insert($data = array(), $replace = false) {
	$fields = $this->implodefields($data);
	$insert = $replace ? 'REPLACE' : 'INSERT';
	$sql = "{$insert} INTO `{$this->db}`.`{$this->table}` (" . implode(', ', $fields[1]) . ") values (" . implode(', ', $fields[2]) . ")";
	$this->query($sql);
	return $this->getInsertId();
    }

    //更新数据
    public function update($data = array(), $where = '') {
	$numargs = func_num_args();
	if ($numargs == 1) {
	    $where = $data;
	    $data = array();
	}
	$fields = $this->implodefields($data);
	$this->condition($where);
	$sql = "UPDATE `{$this->db}`.`{$this->table}` SET " . implode(', ', $fields[0]) . " {$this->condition}";
	$this->query($sql);
	return $this->getAffectedRows();
    }

    //删除数据
    public function delete($where = NULL) {
	if (!is_array($where) && strtolower(substr(trim($where), 0, 6)) == 'delete') {
	    $sql = $where;
	} else {
	    $this->condition($where);
	    $sql = "DELETE  FROM `{$this->db}`.`{$this->table}` {$this->condition}";
	}
	$this->query($sql);
	return $this->getAffectedRows();
    }

    //查询数据
    public function select($where = NULL, $fields = '*') {
	if (!is_array($where) && strtolower(substr(trim($where), 0, 6)) == 'select') {
	    $sql = $where;
	} else {
	    $this->condition($where);
	    $sql = "SELECT {$fields} FROM `{$this->db}`.`{$this->table}` {$this->condition}";
	}
	return $this->fetch($this->query($sql));
    }

    //查询一条数据  
    public function getOne($where, $fields = '*') {
	$data = $this->select($where, $fields = '*');
	if ($data) {
	    return $data[0];
	}
	return array();
    }

    //查询多条数据  
    public function getAll($where, $fields = '*') {
	$data = $this->select($where, $fields = '*');
	return $data;
    }

    //结果数量  
    public function getCount($where = '', $fields = '*') {
	$this->condition($where);
	$sql = "SELECT count({$fields}) as count FROM `{$this->db}`.`{$this->table}` {$this->condition}";
	$data = $this->query($sql);
	if ($data) {
	    return @mysql_result($data, 0);
	}
	return 0;
    }

    //执行sql语句    
    public function query($sql, $flag = '0', $type = '') {
	if ($this->config['dbDebug']) {
	    $startime = $this->microtime_float();
	}

	//查询
	if ($type == 'UNBUFFERED' && function_exists('mysql_unbuffered_query')) {
	    $result = @mysql_unbuffered_query($sql, self::$link);
	} else {
	    $result = @mysql_query($sql, self::$link);
	}

	//重试
	if (in_array(mysql_errno(self::$link), array(2006, 2013)) && empty($result) && $this->config['dbPconnect'] == 0 && !defined('RETRY')) {
	    define('RETRY', true);
	    @mysql_close(self::$link);
	    sleep(2);
	    $this->connect();
	    $result = $this->query($sql);
	}

	if ($result === false) {
	    $this->errdie($sql);
	}

	if ($this->config['dbDebug']) {
	    $endtime = $this->microtime_float();
	    $this->sql[] = array($sql, $endtime - $startime);
	}
	//清空操作数据
	$this->data = array();
	return $flag == '0' ? $result : ($flag == '1' ? $this->getInsertId() : $this->getAffectedRows());
    }

    //返回结果$onlyone为true返回一条否则返回所有,$type有MYSQL_ASSOC,MYSQL_NUM,MYSQL_BOTH
    public function fetch($result, $onlyone = false, $type = MYSQL_ASSOC) {
	if ($result) {
	    if ($onlyone) {
		$row = @mysql_fetch_array($result, $type);
		return $row;
	    } else {
		$rowsRs = array();
		while ($row = @mysql_fetch_array($result, $type)) {
		    $rowsRs[] = $row;
		}
		return $rowsRs;
	    }
	}
	return array();
    }

    //可以运行SELECT，SHOW，EXPLAIN 或 DESCRIBE 等返回一个资源标识符的语句得到返回结果数组
    public function show($sql, $onlyone = false) {
	return $this->fetch($this->query($sql), $onlyone);
    }

    // 使用call函数处理同类型函数  
    private function __call($name, $arguments) {
	$callArr = array('on', 'where', 'order', 'between', 'group', 'limit', 'like', 'having');
	if (in_array($name, $callArr)) {
	    $this->data['condition'][$name] = $arguments[0];
	} else {
	    $this->errdie("function error: function {$name} is not in ($this->class) class exist");
	}
	return $this;
    }

    //返回最后一次插入ID
    public function getInsertId() {
	return @mysql_insert_id(self::$link);
    }

    //返回受影响行数
    public function getAffectedRows() {
	return @mysql_affected_rows(self::$link);
    }

    //获取错误信息
    private function error() {
	return ((self::$link) ? @mysql_error(self::$link) : @mysql_error());
    }

    //获取错误信息ID 
    private function errno() {
	return ((self::$link) ? @mysql_errno(self::$link) : @mysql_errno());
    }

    //获取版本信息
    function version() {
	if (empty($this->version)) {
	    $this->version = mysql_get_server_info(self::$link);
	}
	return $this->version;
    }

    //打印错误信息
    private function errdie($sql = '') {
	if ($this->config['dbDebug']) {
	    die('<B>MySQL ERROR</B></BR>
				 SQL:' . $sql . '</BR>
				 ERRNO:' . $this->errno() . '</BR> 
				 ERROR:' . $this->error() . '</BR>');
	}
	die('DB ERROR！！！');
    }

    //获取时间微妙数
    private function microtime_float() {
	list($usec, $sec) = explode(" ", microtime());
	return ((float) $usec + (float) $sec);
    }

    //析构函数
    public function __destruct() {
	if ($this->config['dbDebug']) {
	    echo '<hr>';
	    print_r($this->sql);
	}
	//unset($this->result);
	//unset($this->condition);
	//unset($this->data);
    }

}